package fun.sanguo.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;

/**
 * 加密工具类
 *
 * @author ZYP
 * @date 2022-07-20
 */
public class EncryptUtils {

    protected static Logger logger = LoggerFactory.getLogger(EncryptUtils.class);

    private static char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    /**
     * 对字符串MD5加密
     *
     * @param src
     * @return
     */
    public static String toMD5(String src) throws Exception {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(src.getBytes());
            // MD5 的计算结果是一个 128 位的长整数，用字节表示就是 16 个字节
            byte[] byteArr = md.digest();
            // 每个字节用 16 进制表示的话，使用两个字符，所以表示成 16 进制需要 32 个字符
            char[] charArr = new char[16 * 2];
            // 表示转换结果中对应的字符位置
            int k = 0;
            // 从第一个字节开始，对 MD5 的每一个字节，转换成 16 进制字符的转换
            for (int i = 0; i < 16; i++) {
                // 取第 i 个字节
                byte byte0 = byteArr[i];
                // 取字节中高 4 位的数字转换，为逻辑右移，将符号位一起右移
                charArr[k++] = hexDigits[byte0 >>> 4 & 0xf];
                // 取字节中低 4 位的数字转换
                charArr[k++] = hexDigits[byte0 & 0xf];
            }
            // 换后的结果转换为字符串
            return new String(charArr);
        } catch (Exception e) {
            logger.error("对字符串MD5加密过程中发生异常，exception={}", e.getMessage());
            throw e;
        }
    }

    /**
     * RSA私钥加密：明文内容→RSA加密后16进制字符串
     *
     * @param content
     * @param key
     * @return
     */
    public static String toRsaHexstrByPrivate(String content, byte[] key) throws Exception {
        return TypeConvertUtils.byteArrayToHexString(toRsaByteArrayByPrivate(content, key));
    }

    /**
     * RSA私钥加密：明文内容→RSA加密后Base64字符串
     *
     * @param content
     * @param key
     * @return
     */
    public static String toRsaBase64ByPrivate(String content, byte[] key) throws Exception {
        return TypeConvertUtils.byteArrayToBase64(toRsaByteArrayByPrivate(content, key));
    }

    /**
     * RSA私钥加密：明文内容→RSA加密后16进制字符串
     *
     * @param content
     * @param key
     * @return
     */
    public static byte[] toRsaByteArrayByPrivate(String content, byte[] key) throws Exception {
        try {
            // 取得私钥
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
            // 实例化密钥工厂
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            // 生成私钥
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            // 创建密码器
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            // 初始化为加密模式的密码器
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            // 内容转换字节
            byte[] byteContent = content.getBytes("UTF-8");
            // 加密并返回
            return cipher.doFinal(byteContent);
        } catch (Exception e) {
            logger.error("RSA私钥加密过程中发生异常，exception={}", e.getMessage());
            throw e;
        }
    }

    /**
     * RSA私钥解密：RSA加密后16进制字符串→明文内容
     *
     * @param content
     * @param key
     * @return
     */
    public static String fromRsaHexstrByPrivate(String content, byte[] key) throws Exception {
        return fromRsaByteArrayByPrivate(TypeConvertUtils.hexStringToByteArray(content), key);
    }

    /**
     * RSA私钥解密：RSA加密后Base64字符串→明文内容
     *
     * @param content
     * @param key
     * @return
     */
    public static String fromRsaBase64ByPrivate(String content, byte[] key) throws Exception {
        return fromRsaByteArrayByPrivate(TypeConvertUtils.base64ToByteArray(content), key);
    }

    /**
     * RSA私钥解密：RSA加密后的字节数组→明文内容
     *
     * @param content
     * @param key
     * @return
     */
    public static String fromRsaByteArrayByPrivate(byte[] content, byte[] key) throws Exception {
        try {
            // 取得私钥
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
            // 实例化密钥工厂
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            // 生成私钥
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            // 创建密码器
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            // 初始化为加密模式的密码器
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            // 解密
            byte[] result = cipher.doFinal(content);
            // 转换为字符串并返回
            return new String(result, "UTF-8");
        } catch (Exception e) {
            logger.error("RSA私钥解密过程中发生异常，exception={}", e.getMessage());
            throw e;
        }
    }
}